package com.dhcc.sdc.api.function;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.dhcc.cdc.busi.entity.*;
import com.dhcc.cdc.busi.service.*;
import com.dhcc.cdc.sys.service.IConfigurationService;
import com.dhcc.cdc.sys.service.IDictionaryService;
import com.dhcc.core.framework.util.CommonUtil;
import com.dhcc.core.framework.util.RedisUtil;
import com.dhcc.core.framework.util.SpringContextHolder;
import com.dhcc.sds.util.StrUtil;
import com.google.common.base.CharMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Component("intheCheckSrv")
public class IntheCheck {

    static ICdcEpisodeService cdcEpisodeService = SpringContextHolder.getBean("cdcEpisodeService");
    static ICdcDiagnosisService cdcDiagnosisService = SpringContextHolder.getBean("cdcDiagnosisService");
    static ICdcDictionaryService cdcDictionaryService = SpringContextHolder.getBean("cdcDictionaryService");
    static ICdcSurgeryService cdcSurgeryService = SpringContextHolder.getBean("cdcSurgeryService");
    static IConfigurationService configurationService = SpringContextHolder.getBean("configurationService");
    static IDictionaryService dictionaryService = SpringContextHolder.getBean("dictionaryService");
    static ICdcEprService cdcEprService = SpringContextHolder.getBean("cdcEprService");
    static ICdcOrdexecService cdcOrdexecService = SpringContextHolder.getBean("cdcOrdexecService");
    static ICdcOrdmastService cdcOrdmastService = SpringContextHolder.getBean("cdcOrdmastService");
    static RedisUtil redisUtil = SpringContextHolder.getBean("redisUtil");

    /**
     * 24小时内出院
     */
    public String in24hOut(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 24小时内死亡
     */
    public String in24hDeath(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 30天重复住院
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String inHos30Days(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 非首次确诊
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String notFirstDiag(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 检查 TODO
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String pACInfo(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 临床试验 TODO
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String clinTest(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 门诊治疗无效 TODO
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String oPFailed(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 年龄
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String ageInfo(Long aEpisodeID, String arg){
        String res = "N";
        CdcEpisodeEntity cdcEpisodeEntity = cdcEpisodeService.selectById(aEpisodeID);
        if (!StringUtils.isEmpty(cdcEpisodeEntity)){
            String ageS=cdcEpisodeEntity.getAge();
            if (CommonUtil.isEmpty(ageS)) return res;
            int age=Integer.parseInt(ageS);
            boolean b = StrUtil.judgeGreaterOrLess(arg, (long) age);
            if (b){
                res = "Y";
            }
        }
        return res;
    }

    /**
     *  全部手术
     *  定义标准：范围用~连接，其他用,连接
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String operInfo(Long aEpisodeID, String arg){
        String res = "N";

        Wrapper<CdcSurgeryEntity> wpr = new EntityWrapper<>();
        wpr.eq("episode_id", aEpisodeID);
        List<CdcSurgeryEntity> cdcSurgeryEntities = cdcSurgeryService.selectList(wpr);
        for (CdcSurgeryEntity cdcSurgeryEntity : cdcSurgeryEntities){
            String code = cdcSurgeryEntity.getCode();
            if (!StringUtils.isEmpty(code)){
                //检查code是否在参数定义范围内
                String s = checkICDArea(code, arg);
                if (Objects.equals("Y", s)){
                    res = "Y";
                    break;
                }
            }
        }
        return res;
    }

    /**
     *  主要手术
     *  定义标准：范围用~连接，其他用,连接
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String mainOperInfo(Long aEpisodeID, String arg){
        return operInfo(aEpisodeID, arg);
    }

    /**
     * 主要操作
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String handleInfo(Long aEpisodeID, String arg) {
        String res = "N";
        Wrapper<CdcSurgeryEntity> wpr = new EntityWrapper<>();
        wpr.eq("episode_id", aEpisodeID);
        List<CdcSurgeryEntity> cdcSurgeryEntities = cdcSurgeryService.selectList(wpr);
        for (CdcSurgeryEntity cdcSurgeryEntity : cdcSurgeryEntities){
            String code = cdcSurgeryEntity.getCode();
            if (!StringUtils.isEmpty(code)){
                //检查code是否在参数定义范围内
                String s = checkICDArea(code, arg);
                if (Objects.equals("Y", s)){
                    res = "Y";
                    break;
                }
            }
        }
        return res;
    }

    /**
     * 孕期 TODO
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String pregnant(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 主要诊断
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String getDiagInfo(Long aEpisodeID, String arg){
        String res = "N";
        String diagICD = "";
        String diagDesc = "";
        //诊断数据来源 1:病历首页2:病案编目3:临床;
        //默认诊断数据来源为病案编目3
        String dataSource="2";
        if (Objects.equals("1", dataSource)){
            //TODO
        }else if (Objects.equals("2", dataSource)){
            //查询病案编目诊断信息
            List<CdcDiagnosisEntity> diagnosisEntities = cdcDiagnosisService.selectDiagInfo(aEpisodeID, null, null);
            for (CdcDiagnosisEntity cdcDiagnosisEntity : diagnosisEntities){
                //主诊断
                if (Objects.equals(1, cdcDiagnosisEntity.getIsMain())){
                    diagICD = cdcDiagnosisEntity.getIcd10();
                    diagDesc = cdcDiagnosisEntity.getDescription();
                    if (!StringUtils.isEmpty(diagICD)){
                        //匹配诊断ICD是否符合准入标准
                        String s = checkICDArea(diagICD, arg);
                        if (Objects.equals("Y", s)){
                            res = "Y";
                            break;
                        }
                    }
                    if (CommonUtil.isNotEmpty(diagDesc)) {
                        //匹配诊断描述是否符合准入标准
                        String s = checkKeyArea(diagDesc, arg);
                        if (Objects.equals("Y", s)){
                            res = "Y";
                            break;
                        }
                    }
                }
            }
        }else if (Objects.equals("3", dataSource)){
            //TODO
        }

        return res;
    }

    /**
     * 全部诊断
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String getAllDiagInfo(Long aEpisodeID, String arg){
        String res = "N";
        String diagICD = "";
        String diagDesc = "";
        //诊断数据来源 1:病历首页2:病案编目3:临床;
        //默认诊断数据来源为病案编目3
        String dataSource="2";
        if (Objects.equals("1", dataSource)){
            //TODO
        }else if (Objects.equals("2", dataSource)){
            //查询病案编目诊断信息
            List<CdcDiagnosisEntity> diagnosisEntities = cdcDiagnosisService.selectDiagInfo(aEpisodeID, null, null);
            for (CdcDiagnosisEntity cdcDiagnosisEntity : diagnosisEntities){
                diagICD = cdcDiagnosisEntity.getIcd10();
                if (!StringUtils.isEmpty(diagICD)){
                    //匹配诊断是否符合准入标准
                    String s = checkICDArea(diagICD, arg);
                    if (Objects.equals("Y", s)){
                        res = "Y";
                        break;
                    }
                }
                if (CommonUtil.isNotEmpty(diagDesc)) {
                    //匹配诊断描述是否符合准入标准
                    String s = checkKeyArea(diagDesc, arg);
                    if (Objects.equals("Y", s)){
                        res = "Y";
                        break;
                    }
                }
            }
        }else if (Objects.equals("3", dataSource)){
            //TODO
        }

        return res;
    }

    /**
     * 住院日
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String inHosDays(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 转院
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String hosTransInfo(Long aEpisodeID, String arg){
        String res = "N";
        return res;
    }

    /**
     * 感染信息
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String infMsg(Long aEpisodeID, String arg){
        String res = "N";
        if (Objects.equals("HCAP", arg)){
            //感染系统没找到HCAP定义，HAP处理
            arg = "HAP";
        }

        return res;
    }

    /**
     * 次要诊断
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String oDIagInfo(Long aEpisodeID, String arg){
        String res = "N";
        //次要诊断
        List<CdcDiagnosisEntity> diagnosisEntities = cdcDiagnosisService.selectDiagInfo(aEpisodeID, null, null);
        for (CdcDiagnosisEntity cdcDiagnosisEntity : diagnosisEntities){
            if (cdcDiagnosisEntity.getIsMain()!=1) {
                String s = checkICDArea(cdcDiagnosisEntity.getIcd10(), arg);
                if (Objects.equals("Y", s)){
                    res = "Y";
                    break;
                }
                String r = checkKeyArea(cdcDiagnosisEntity.getDescription(), arg);
                if (Objects.equals("Y", r)){
                    res = "Y";
                    break;
                }
            }
        }
        return res;
    }

    /**
     * 医嘱
     * @param aEpisodeID
     * @param arg
     * @return
     */
    public String orderInfo(Long aEpisodeID, String arg){
        String res = "N";
        // 无效医嘱
        List<Long> invalidOrderStatus = new ArrayList<>();
        if (redisUtil.hasKey("ORD_STAT_C")) {
            invalidOrderStatus.add(Long.valueOf(redisUtil.get("ORD_STAT_C")));
        } else {
            CdcDictionaryEntity cdcDictionaryEntity = dictionaryService.getMatchCtDic("SDS", "SDMatchCdcDic", "ORD_STAT_C");// 撤销-医嘱状态
            if (cdcDictionaryEntity != null) {
                redisUtil.set("ORD_STAT_C", cdcDictionaryEntity.getId());
                invalidOrderStatus.add(cdcDictionaryEntity.getId());
            }
        }
        if (redisUtil.hasKey("ORD_STAT_U")) {
            invalidOrderStatus.add(Long.valueOf(redisUtil.get("ORD_STAT_U")));
        } else {
            CdcDictionaryEntity cdcDictionaryEntity = dictionaryService.getMatchCtDic("SDS", "SDMatchCdcDic", "ORD_STAT_U");// 作废-医嘱状态
            if (cdcDictionaryEntity != null) {
                redisUtil.set("ORD_STAT_U", cdcDictionaryEntity.getId());
                invalidOrderStatus.add(cdcDictionaryEntity.getId());
            }
        }

        // 取得全部医嘱
        Wrapper<CdcOrdexecEntity> wpr = new EntityWrapper<>();
        wpr.eq("episode_id", aEpisodeID).notIn("bus_order_status_id", invalidOrderStatus);
        List<CdcOrdexecEntity> orderList = cdcOrdexecService.selectList(wpr);
        for (CdcOrdexecEntity ordExec : orderList) {
            CdcOrdmastEntity ordMast = cdcOrdmastService.selectById(ordExec.getOrderMastId());
            String s = checkKeyArea(ordMast.getDescription(), arg);
            if (Objects.equals("Y", s)){
                res = "Y";
                break;
            }
        }
        return res;
    }

    /**
     * 准入ICD范围检查方法
     * @param operCode
     * @param aOper
     * @return
     */
    public String checkICDArea(String operCode, String aOper){
        String res = "N";
        if (CommonUtil.isEmpty(operCode) || CommonUtil.isEmpty(aOper)) {
            return res;
        }
        aOper = aOper.replace("，", ",");
        aOper = aOper.replace("、", ",");
        aOper = aOper.replace("——", "~");
        aOper = aOper.replace("-", "~");
        if (operCode.contains("+")){
            String[] split = operCode.split("\\+");
            operCode = split[0];
        }
        if (operCode.contains(".")){
            operCode = operCode.split("\\.")[0]+"."+operCode.split("\\.")[1].replaceAll("x", "0");
        }
        //定义operCode的字母和数字
        String a1 = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).retainFrom(operCode);
        String s3 = CharMatcher.inRange('0', '9').or(CharMatcher.is('.')).retainFrom(operCode);
        /*long l3 = Long.parseLong(s3);*/
        long l3 = StrUtil.strToLong(s3);

        if (!StringUtils.isEmpty(operCode) && !StringUtils.isEmpty(aOper)){
            if (aOper.contains(operCode)){
                //1.直接包含
                res = "Y";
            }else {
                //2.有范围查询是否在范围内
                if (aOper.contains("~") && !aOper.contains(",")){
                    //只有一个范围的情况
                    String[] split = aOper.split("~");
                    //字母获取
                    String a2 = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).retainFrom(split[0]);
                    //数字获取
                    String s1 = CharMatcher.inRange('0', '9').or(CharMatcher.is('.')).retainFrom(split[0]);
                    String s2 = CharMatcher.inRange('0', '9').or(CharMatcher.is('.')).retainFrom(split[1]);
                    //字母判断
                    if (Objects.equals(a1, a2)){
                        long l1 = StrUtil.strToLong(s1);
                        long l2 = StrUtil.strToLong(s2);
                        if (l1 < l3 && l3 < l2){
                            res = "Y";
                        } else if (s3.indexOf(s1)==0||s3.indexOf(s2)==0) {
                            res = "Y";
                        }
                    }
                }else if (aOper.contains(",")){
                    //多个范围，满足一个退出
                    String[] split = aOper.split(",");
                    for (String s : split){
                        if (s.contains("~")){
                            String[] split1 = s.split("~");
                            //字母获取
                            String a2 = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).retainFrom(split1[0]);
                            //数字获取
                            String s1 = CharMatcher.inRange('0', '9').or(CharMatcher.is('.')).retainFrom(split1[0]);
                            String s2 = CharMatcher.inRange('0', '9').or(CharMatcher.is('.')).retainFrom(split1[1]);
                            //字母判断
                            if (Objects.equals(a1, a2)){
                                long l1 = StrUtil.strToLong(s1);
                                long l2 = StrUtil.strToLong(s2);
                                if (l1 < l3 && l3 < l2){
                                    res = "Y";
                                    break;
                                }else if (s3.indexOf(s1)==0||s3.indexOf(s2)==0) {
                                    res = "Y";
                                    break;
                                }
                            }
                        } else {
                            //字母获取
                            String a2 = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).retainFrom(s);
                            //数字获取
                            String s1 = CharMatcher.inRange('0', '9').or(CharMatcher.is('.')).retainFrom(s);
                            //字母判断
                            if (Objects.equals(a1, a2)) {
                                if (s3.indexOf(s1)==0) {
                                    res = "Y";
                                    break;
                                }
                            }
                        }
                    }
                } else {
                    //字母获取
                    String a2 = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).retainFrom(aOper);
                    //数字获取
                    String s1 = CharMatcher.inRange('0', '9').or(CharMatcher.is('.')).retainFrom(aOper);
                    //字母判断
                    if (Objects.equals(a1, a2)) {
                        if (s3.indexOf(s1)==0) {
                            res = "Y";
                        }
                    }
                }
            }
        }
        return res;
    }

    /**
     * 准入关键词检查方法
     * @param targetStr
     * @param keyWords
     * @return
     */
    public String checkKeyArea(String targetStr, String keyWords){
        String res = "N";
        if (CommonUtil.isEmpty(targetStr) || CommonUtil.isEmpty(keyWords)) {
            return res;
        }
        keyWords = keyWords.replace("，", ",");
        keyWords = keyWords.replace("、", ",");
        keyWords = keyWords.replace("——", "~");
        keyWords = keyWords.replace("-", "~");
        targetStr = targetStr.replace("，",",");
        targetStr = targetStr.replace("——", "~");
        targetStr = targetStr.replace("-","~");
        String[] split = keyWords.split(",");
        for (String s : split) {
            Boolean isContain = false;
            String[] parArr = s.split("&");
            for(String par:parArr){
                if (targetStr.contains(par)) {
                    isContain=true;
                }else{
                    isContain = false;
                    break;
                }
            }
            if(isContain){
                res = "Y";
                break;
            }
        }
        return res;
    }
}
